package com.yexiao.core.util;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.yexiao.core.exception.BusinessException;
import lombok.NonNull;

import java.util.ArrayList;
import java.util.List;

@SuppressWarnings("all")
public class JSONUtil {

    public static String getString(JSONObject param, String key){
        return (String)param.get(key);
    }

    public static JSONObject of() {
        return new JSONObject();
    }

    /**
     * 动态构建 JSONObject
     * @param keyAndValues 键值对参数，需按 key1, value1, key2, value2... 格式传入
     */
    public static JSONObject of(Object... keyAndValues) {
        if(keyAndValues.length % 2 != 0) {
            throw new BusinessException("键值对数量必须为偶数");
        }

        JSONObject jsonObject = of();
        for(int i = 0; i < keyAndValues.length; i += 2) {
            Object k = keyAndValues[i];
            if(!(k instanceof String)) {
                throw new BusinessException("key 必须为字符串。key:" + k.toString());
            }

            Object v = keyAndValues[i + 1];
            jsonObject.put((String)k, v);
        }
        return jsonObject;
    }

    /**
     * 将JSON对象转换为 JSON字符串
     */
    public static String toJSON(Object obj) {
        if (obj == null) {
            return null;
        } else {
            return obj instanceof String ? (String)obj : JSON.toJSONString(obj);
        }
    }

    public static JSONObject toJSONObject(Object obj) {
        return toBean(obj, new TypeReference<JSONObject>() {
        });
    }

    public static JSONArray toJSONArray(Object obj) {
        return toBean(obj, new TypeReference<JSONArray>() {
        });
    }

    public static <T> T toBean(Object obj, Class<T> tClass) {
        String jsonStr = toJSON(obj);
        if(StrUtil.isEmpty(jsonStr)) {
            return null;
        } else if(tClass == String.class) {
            return (T) obj.toString();
        } else {
            try {
                return JSONObject.parseObject(jsonStr, tClass);
            } catch (Exception var4) {
                return null;
            }
        }
    }

    public static <T> T toBean(Object obj, TypeReference<T> valueTypeRef) {
        String json = toJSON(obj);
        if (!StrUtil.isEmpty(json) && valueTypeRef != null) {
            if (valueTypeRef.getType().equals(String.class)) {
                return (T) obj.toString();
            } else {
                try {
                    return JSONObject.parseObject(json, valueTypeRef);
                } catch (Exception var4) {
                    return null;
                }
            }
        } else {
            return null;
        }
    }

    public static <T> List<T> toList(String json, Class<T> tClass) {
        JSONArray jsonArray = toJSONArray(json);
        return (List)(CollectionUtil.isEmpty(jsonArray) ? new ArrayList() : JSONArray.parseArray(jsonArray.toJSONString(), tClass));
    }

    public static <T> T get(JSONObject param, @NonNull TypeReference<T> valueTypeRef, String... levelParams) {
        if (param != null && levelParams != null) {
            try {
                for(int i = 0; i < levelParams.length; ++i) {
                    if (i == levelParams.length - 1) {
                        Object value = param.get(levelParams[i]);
                        if (ObjectUtil.equal(valueTypeRef.getType(), Integer.class)) {
                            return (T) FormatUtil.toInt(value);
                        }

                        if (ObjectUtil.equal(valueTypeRef.getType(), Long.class)) {
                            return (T) FormatUtil.toLong(value);
                        }

                        return (T) toBean(toJSON(value), (TypeReference)valueTypeRef);
                    }

                    param = param.getJSONObject(levelParams[i]);
                }

                return null;
            } catch (Exception var5) {
                return null;
            }
        } else {
            return null;
        }
    }

    /* ==== String ==== */
    public static String getStr(JSONObject param, String key) {
        return (String)get(param, new TypeReference<String>() {
        }, key);
    }

    public static String getStrDef(JSONObject param, String defaultVal, String key) {
        String value = getStr(param, key);
        return StrUtil.isNotEmpty(value) ? value : defaultVal;
    }

    public static String checkAndGetStr(JSONObject param, String key) {
        String str = getStr(param, key);
        if(StrUtil.isEmpty(str)) {
            throw new BusinessException(getParamLackErrorMsg(key));
        }

        return str;
    }

    /* ==== Integer ==== */
    public static Integer getInt(JSONObject param, String key) {
        return (Integer)get(param, new TypeReference<Integer>() {
        }, key);
    }

    public static Integer getIntDef(JSONObject param, Integer defaultVal, String key) {
        Integer value = getInt(param, key);
        return value != null ? value : defaultVal;
    }

    public static Integer checkAndGetInt(JSONObject param, String key) {
        Integer num = getInt(param, key);
        checkIsNull(num, key);
        return num;
    }

    /* ==== Long ==== */
    public static Long getLong(JSONObject param, String key) {
        return (Long) get(param, new TypeReference<Long>() {}, key);
    }

    public static Long getLongDef(JSONObject param, Long defaultValue, String key) {
        Long value = getLong(param, key);
        return value != null ? value : defaultValue;
    }

    public static Long checkAndGetLong(JSONObject param, String key) {
        Long value = getLong(param, key);
        checkIsNull(value, key);
        return value;
    }

    /* ==== Double ==== */
    public static Double getDouble(JSONObject param, String key) {
        return (Double) get(param, new TypeReference<Double>() {}, key);
    }

    public static Double getDoubleDef(JSONObject param, Double defaultValue, String key) {
        return getDouble(param, key) == null ? defaultValue : getDouble(param, key);
    }

    public static Double checkAndGetDouble(JSONObject param, String key) {
        Double value = getDouble(param, key);
        checkIsNull(value, key);
        return value;
    }

    /* ==== JSONObject ==== */
    public static JSONObject getJSONObject(JSONObject param, String key) {
        return (JSONObject)get(param, new TypeReference<JSONObject>() {
        }, key);
    }

    /* ==== List ==== */
    public static <T> List<T> getList(JSONObject param, Class<T> tClass, String key) {
        Object o = get(param, new TypeReference<Object>() {
        }, key);
        if (o == null) {
            return new ArrayList();
        } else {
            try {
                return JSONArray.parseArray(JSON.toJSONString(o), tClass);
            } catch (Exception var5) {
                var5.printStackTrace();
                return new ArrayList();
            }
        }
    }

    private static String getParamLackErrorMsg(String key) {
        return "参数：" + key + "不存在";
    }

    private static <T> void checkIsNull(T value, String key) {
        if(value == null) {
            throw new BusinessException(getParamLackErrorMsg(key));
        }

        if(StrUtil.isBlank(String.valueOf(value))) {
            throw new BusinessException(getParamLackErrorMsg(key));
        }
    }

}
